#ifndef _MCU_GPIO_H_
#define _MCU_GPIO_H_

#include "mcu.h"

#define __GPIOCONNECT(A,B)   A##B
#define _GPIOCONNECT(A,B)   __GPIOCONNECT(A,B)
#define GPIOCONNECT(A,B)    _GPIOCONNECT(A,B)

#if (defined PY32F002Bx5)
    #define GPIO_PA0_AF0_SPI_MOSI   0
    #define GPIO_PA0_AF2_TIM1_CH1   2

    #define GPIO_PA1_AF0_SPI_MISO   0
    #define GPIO_PA1_AF2_TIM1_CH2   2

    #define GPIO_PA2_AF0_SWCLK      0
    #define GPIO_PA2_AF1_USART_RX   1
    #define GPIO_PA2_AF2_TIM1_CH4   2
    #define GPIO_PA2_AF4_CMP2_OUT   4
    #define GPIO_PA2_AF6_I2C_SCL    6

    #define GPIO_PA3_AF1_USART_TX   1
    #define GPIO_PA3_AF2_TIM1_CH2   2

    #define GPIO_PA4_AF1_USART_RX   1
    #define GPIO_PA4_AF2_TIM1_CH3   2
    #define GPIO_PA4_AF5_TIM14_CH1  5

    #define GPIO_PA5_AF1_USART_CK   1
    #define GPIO_PA5_AF2_TIM1_CH1   2
    #define GPIO_PA5_AF5_TIM14_CH1  5

    #define GPIO_PA6_AF0_SPI_NSS    0
    #define GPIO_PA6_AF1_USART_TX   1
    #define GPIO_PA6_AF7_EVENTOUT   7

    #define GPIO_PA7_AF0_SPI_MOSI   0
    #define GPIO_PA7_AF1_USART_TX   1
    #define GPIO_PA7_AF2_TIM1_CH4   2
    #define GPIO_PA7_AF3_USART_RX   3
    #define GPIO_PA7_AF4_MCO        4

    #define GPIO_PB0_AF0_SPI_SCK    0
    #define GPIO_PB0_AF1_USART_CK   1
    #define GPIO_PB0_AF2_TIM1_CH2   2
    #define GPIO_PB0_AF3_TIM1_CH3N  3

    #define GPIO_PB1_AF1_USART_RTS  1
    #define GPIO_PB1_AF2_TIM1_CH2N  2
    #define GPIO_PB1_AF3_TIM1_CH4   3
    #define GPIO_PB1_AF4_MCO        4

    #define GPIO_PB2_AF0_SPI_SCK    0
    #define GPIO_PB2_AF1_USART_CTS  1
    #define GPIO_PB2_AF2_TIM1_CH1N  2
    #define GPIO_PB2_AF3_TIM1_CH3   3

    #define GPIO_PB3_AF1_USART_CK   1
    #define GPIO_PB3_AF2_TIM1_ETR   2
    #define GPIO_PB3_AF4_CMP1_OUT   4
    #define GPIO_PB3_AF6_I2C_SCL    6

    #define GPIO_PB4_AF1_USART_TX   1
    #define GPIO_PB4_AF2_TIM1_BKIN  2
    #define GPIO_PB4_AF6_I2C_SDA    6

    #define GPIO_PB5_AF0_SPI_NSS    0
    #define GPIO_PB5_AF1_USART_RX   1
    #define GPIO_PB5_AF2_TIM1_CH3   2
    #define GPIO_PB5_AF5_TIM14_CH1  5

    #define GPIO_PB6_AF0_SWDIO      0
    #define GPIO_PB6_AF1_USART_TX   1
    #define GPIO_PB6_AF2_SPI_MISO   2
    #define GPIO_PB6_AF6_I2C_SDA    6

    #define GPIO_PB7_AF0_SPI_MOSI   0
    #define GPIO_PB7_AF5_TIM14_CH1  5

    #define GPIO_PC0_AF0_SWDIO      0
    #define GPIO_PC0_AF2_TIM1_CH1N  2
    #define GPIO_PC0_AF7_EVENTOUT   7

    #define GPIO_PC1_AF0_SPI_MISO   0

#endif



typedef struct _gpio_pins_t
{
    __IO uint32_t pin0                     : 1;
    __IO uint32_t pin1                     : 1;
    __IO uint32_t pin2                     : 1;
    __IO uint32_t pin3                     : 1;
    __IO uint32_t pin4                     : 1;
    __IO uint32_t pin5                     : 1;
    __IO uint32_t pin6                     : 1;
    __IO uint32_t pin7                     : 1;
    __IO uint32_t pin8                     : 1;
    __IO uint32_t pin9                     : 1;
    __IO uint32_t pin10                    : 1;
    __IO uint32_t pin11                    : 1;
    __IO uint32_t pin12                    : 1;
    __IO uint32_t pin13                    : 1;
    __IO uint32_t pin14                    : 1;
    __IO uint32_t pin15                    : 1;
    __IO uint32_t RSV                      : 16;
} gpio_pins_t;


/**
 * 按照配置文件初始化GPIO，这里没有开启时钟
 */
void Gpio_Init();

// /**
//  * 获取Pin电平。
//  * @param pin_name pin0 ~ pin15
//  */
// #define Gpio_GetPin(GPIOx, pin_name) ((gpio_pins_t)GPIOx->IDR).pin_name

/**
 * 获取Pin电平。
 * @param pin_num 0~15常量
 */
#define Gpio_GetPin(GPIOx, pin_num)  GPIOCONNECT(((gpio_pins_t *)&GPIOx->IDR)->pin, pin_num)

/**
 * 设置Pin高电平
 * @param pin_num 0~15
 */
#define Gpio_SetPin(GPIOx, pin_num) GPIOx->BSRR = (1 << pin_num)
#define Gpio_SetPinHigh  Gpio_SetPin
/**
 * 设置Pin低电平
 * @param pin_num 0~15
 */
#define Gpio_ClrPin(GPIOx, pin_num) GPIOx->BRR = (1 << pin_num)
#define Gpio_SetPinLow  Gpio_ClrPin
/**
 * 翻转 Pin
 */
#define Gpio_TogglePin(GPIOx, pin_num) WRITE_REG(GPIOx->ODR, READ_REG(GPIOx->ODR) ^ (1 << pin_num))

#define GPIO_MODE_INPUT                 0
#define GPIO_MODE_OUTPUT                1
#define GPIO_MODE_ALTERNATE             2
#define GPIO_MODE_ANALOG                3
/**
 * 设置 Pin 模式
 * @param mode GPIO_MODE_INPUT GPIO_MODE_OUTPUT GPIO_MODE_ALTERNATE GPIO_MODE_ANALOG
 */
#define Gpio_SetMode(GPIOx, pin_num, mode) \
{   \
    MODIFY_REG(GPIOx->MODER, GPIO_MODER_MODE0_Msk << (pin_num * 2), mode << (pin_num * 2)); \
}

/**
 * 设置复用功能
 */
#define Gpio_SetAF(GPIOx, pin_num, af) \
{   \
    MODIFY_REG(GPIOx->AFR[0], GPIO_AFRL_AFSEL0_Msk << (pin_num * 4), af << (pin_num * 4)); \
}

#define GPIO_NO_PULL    0
#define GPIO_PULL_UP    1
#define GPIO_PULL_DOWN  2
/**
 * 设置上下拉
 */
#define Gpio_SetPuPd(GPIOx, pin_num, pupd)  \
{   \
    MODIFY_REG(GPIOx->PUPDR, GPIO_PUPDR_PUPD0_Msk << (pin_num * 2), pupd << (pin_num * 2)); \
}

#endif
